package com.ddd.codegeneration.serviceImpl;

import com.ddd.codegeneration.entity.entity.Attribute;
import com.ddd.codegeneration.service.GeneratorBackEndService;
import com.ddd.codegeneration.utils.FreeMarkerTemplateUtils;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.*;
import java.util.List;
import java.util.Map;

/**
 * @author 官江涛
 * @version 1.0
 * @Title: 代码生成器
 * @date 2018/7/23/10:20
 */
@Component
@Transactional
public class GeneratorBackEndServiceImpl implements GeneratorBackEndService {

    /**
     * entity路径
     */
    private static String entityPath = "E:\\java-workspace\\codegeneration\\src\\main\\java\\com\\ddd\\codegeneration\\entity\\entity\\";
    /**
     * service路径
     */
    private static String servicePath = "E:\\java-workspace\\codegeneration\\src\\main\\java\\com\\ddd\\codegeneration\\service\\";
    /**
     * serviceImpl路径
     */
    private static String serviceImplPath = "E:\\java-workspace\\codegeneration\\src\\main\\java\\com\\ddd\\codegeneration\\serviceImpl\\";
    /**
     * controller路径
     */
    private static String controllerPath = "E:\\java-workspace\\codegeneration\\src\\main\\java\\com\\ddd\\codegeneration\\controller\\";
    /**
     * mapper路径
     */
    private static String mapperPath = "E:\\java-workspace\\codegeneration\\src\\main\\java\\com\\ddd\\codegeneration\\dao\\mapper\\";
    /**
     * XMLmapper路径
     */
    private static String xmlPath = "E:\\java-workspace\\codegeneration\\src\\main\\resources\\Mapper\\";
    /**
     * 实体生成器
     * @param attrs  需要解析的参数
     * @param entityPath
     * @return 返回实体的类路径
     */
    @Override
    public String generateEntity(Map<String, Object> attrs, String entityPath) {
        final String templateName = "Entity.ftl";
        final String suffix = ".java";
        final String path = entityPath + attrs.get("className") + suffix;
        generateFileByTemplate(templateName, attrs, path);
        return ( attrs.get("entityPackageName")).toString() +"." + attrs.get("className");
    }

    /**
     * service生成器
     * @param root 需要解析的参数
     * @param servicePath  文件存储路径
     * @return
     */
    @Override
    public int generateService(Map<String, Object> root, String servicePath) {
        final String templateName = "Service.ftl";
        final String suffix = "Service.java";
        final String path = servicePath + root.get("className") + suffix;
        generateFileByTemplate(templateName, root, path);
        return 1;
    }

    /**
     * serivceImpl生成器
     * @param root 需要解析的参数
     * @param serviceImplPath  文件存储路径
     * @return
     */
    @Override
    public int generateServiceImpl(Map<String, Object> root, String serviceImplPath ) {
        final String templateName = "ServiceImplments.ftl";
        final String suffix = "ServiceImpl.java";
        final String path = serviceImplPath + root.get("className") + suffix;
        generateFileByTemplate(templateName, root, path);
        return 1;
    }

    /**
     * controller生成器
     * @param root  需要解析的参数
     * @param controllerPath 文件存储路径
     * @return
     */
    @Override
    public int generateController(Map<String, Object> root, String controllerPath) {
        final String templateName = "Controller.ftl";
        final String suffix = "Controller.java";
        final String path = controllerPath + root.get("className") + suffix;
        generateFileByTemplate(templateName, root, path);
        return 1;
    }

    /**
     * JavaMapper生成器
     * @param root 需要解析的参数
     * @param mapperPath 文件存储路径
     * @return
     */
    @Override
    public int generateJavaMapper(Map<String, Object> root, String mapperPath) {
        final String templateName = "Mapper.ftl";
        final String suffix = "Mapper.java";
        final String path = mapperPath + root.get("className") + suffix;
        generateFileByTemplate(templateName, root, path);
        return 1;
    }

    /**
     * XMLMapper生成器
     * @param root 需要解析的参数
     * @param xmlPath 文件存储路径
     * @return
     */
    @Override
    public int generateXMLMapper(Map<String, Object> root, String xmlPath) {
        String params = conectStr((List<Attribute>) root.get("attrs"));
        String selectAll = "SELECT * FROM  " + root.get("className");
        String selectByPrimaryKey = "SELECT * FROM  "+ root.get("className")+" WHERE id = #{id}";
        String deleteByPrimaryKey = "DELETE FROME "+ root.get("className")+" WHERE id = #{id}";
        String updateByPrimaryKey = "UPDATE "+ root.get("className")+" set" + getSQL((List<Attribute>) root.get("attrs"));
        String insert = "INSERT INTO "+ root.get("className")+" "+ conectStr((List<Attribute>) root.get("attrs")) + " VALUES (" + getInsertValues((List<Attribute>) root.get("attrs")) + " ) ";
        root.put("params",params);
        root.put("selectAll",selectAll);
        root.put("selectByPrimaryKey",selectByPrimaryKey);
        root.put("deleteByPrimaryKey",deleteByPrimaryKey);
        root.put("updateByPrimaryKey",updateByPrimaryKey);
        root.put("insert",insert);
        final String templateName = "MapperXML.ftl";
        final String suffix = "Mapper.xml";
        final String path = xmlPath + root.get("className") + suffix;
        generateFileByTemplate(templateName, root, path);
        return 1;
    }

    /**
     * 获取新增字符串的字段
     * @param attributes
     * @return
     */
    private String getInsertValues(List<Attribute> attributes) {
        StringBuffer stringBuffer = new StringBuffer();
        attributes.forEach(
                (attr) ->
                        stringBuffer.append(" #{"+attr.getName()+ "},"));
        stringBuffer.deleteCharAt(stringBuffer.length() - 1);
        return stringBuffer.toString();
    }

    /**
     * 获取现有参数的字段
     * @param attributes
     * @return
     */
    private String getSQL(List<Attribute> attributes){
        StringBuffer stringBuffer = new StringBuffer();
        attributes.forEach(
                (attr) -> stringBuffer.append(attr.getName() + " = " + "#{"+attr.getName()+ "},"));
        stringBuffer.deleteCharAt(stringBuffer.length() - 1);
        return stringBuffer.toString();
    }

    /**
     * 拼接出生成XML文件需要的参数
     * @param attributes  字段列表
     * @return  参数字符串
     */
    private String conectStr(List<Attribute> attributes) {
        StringBuffer stringBuffer = new StringBuffer();
        attributes.forEach(
                (attr) -> stringBuffer.append(attr.getName()+ ","));
        stringBuffer.deleteCharAt(stringBuffer.length() - 1);
        return stringBuffer.toString();
    }

    /**
     * 代码生成器
     * @param templateName  使用的模板名称
     * @param attrs 赋值的参数
     * @param path  生成的路径
     */
    private static void generateFileByTemplate(String templateName, Map<String, Object> attrs, String path){
        File file = new File(path);
        Template template = null;
        try {
            template = FreeMarkerTemplateUtils.getTemplate(templateName);
            FileOutputStream fos = new FileOutputStream(file);
            Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"),10240);
            template.process(attrs,out);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TemplateException e) {
            e.printStackTrace();
        }
    }
}
